package club.justwill.single.Service.impl;

import club.justwill.single.Service.PayService;
import club.justwill.single.bean.RefundData;
import club.justwill.single.impl.ToolsImpl;
import club.justwill.single.model.*;
import club.justwill.single.persistence.dao.OrderDao;
import club.justwill.single.persistence.document.ProjectSupport;
import club.justwill.single.persistence.document.SkuSupport;
import club.justwill.single.persistence.document.SupportUser;
import club.justwill.single.persistence.document.UserSupportProject;
import club.justwill.single.persistence.jpo.OrderItem;
import club.justwill.single.persistence.jpo.Orders;
import club.justwill.single.persistence.jpo.User;
import club.justwill.single.persistence.store.ProjectSupportStore;
import club.justwill.single.persistence.store.SkuSupoortStore;
import club.justwill.single.persistence.store.UserSupportProjectStore;
import club.justwill.single.util.AlipayCore;
import club.justwill.single.util.AlipaySubmit;
import club.justwill.single.util.JsonResponseHelper;
import club.justwill.single.util.sign.RSA;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.*;

/**
 * Created by xiangnan on 16-2-2.
 */
@Service
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class PayServiceImpl extends BaseService implements PayService {

    @Value("${pay.notify_url}")
    private String notifyUrl;

    @Value("${pay.return_url}")
    private String returnUrl;

    @Value("${pay.home_url}")
    private String homeUrl;

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private ProjectSupportStore projectSupportStore;

    @Autowired
    private UserSupportProjectStore userSupportProjectStore;

    @Autowired
    private SkuSupoortStore skuSupoortStore;

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = true)
    public String payOrderByWeiChat(Long orderId, SecurityToken token, JsonResponse obj) {
        Orders order = orderDao.getByOrderId(orderId);
        if(order == null) {
            JsonResponseHelper.addError(obj, CoreConstants.ORDER_INVIAL);
        } else if (order.getStatus() == OrderStatus.ORDER_PAID) {
            JsonResponseHelper.addError(obj, CoreConstants.ORDER_PAID_ALREADY);
        } else {
            double price = 0L;
            String name = "";
            for(OrderItem orderItem: order.getOrderItemSet()) {
                price += orderItem.getSkus().getUnitprice() * orderItem.getUnits() + orderItem.getSkus().getDispatchPrice();
                name = orderItem.getSkus().getName();
            }
            DecimalFormat df = new DecimalFormat("######0.00");
            Map<String, String> sParaTemp = new HashMap<String, String>();
            sParaTemp.put("service", "alipay.wap.create.direct.pay.by.user");
            sParaTemp.put("partner", AlipayConfig.partner);
            sParaTemp.put("seller_id", AlipayConfig.seller_id);
            sParaTemp.put("_input_charset", AlipayConfig.input_charset);
            sParaTemp.put("payment_type", "1");
            sParaTemp.put("notify_url", notifyUrl);
//            sParaTemp.put("return_url", returnUrl);
            sParaTemp.put("out_trade_no", String.valueOf(orderId));
            System.out.println(String.valueOf(orderId));
            sParaTemp.put("subject", name);
            sParaTemp.put("total_fee", String.valueOf(df.format(price)));
            sParaTemp.put("show_url", homeUrl);
            sParaTemp.put("body", name);
            sParaTemp.put("it_b_pay", "5000");
            sParaTemp.put("extern_token", "");

            //建立请求
            String sHtmlText = AlipaySubmit.buildRequest(sParaTemp, "get", "确认");
            return sHtmlText;
        }
        return null;
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public Boolean refreshOrder(Long orderId, SecurityToken token, String tradeNumber) {
        Orders order = orderDao.getByOrderId(orderId);
        if(order == null) {
            return false;
        } else if (order.getStatus() == OrderStatus.ORDER_PAID) {
            return false;
        } else {
            User user = order.getUser();
            double price = 0L;
            int num = 0;
            Long projectId = 0L;
            for(OrderItem orderItem: order.getOrderItemSet()) {
                price += orderItem.getSkus().getUnitprice() * orderItem.getUnits();
                projectId = orderItem.getSkus().getProjectId();
                num += orderItem.getUnits();
            }
            SupportUser supportUser = new SupportUser(user.getNickName(), price, num, new Date(), user.getHeadIcon(), tradeNumber);
            ProjectSupport projectSupport = projectSupportStore.searchProjectSupport(projectId);
            if(projectSupport == null) {
                projectSupport = new ProjectSupport(projectId, 0.0, 0, new ArrayList<SupportUser>());
            }
            projectSupport.setGetFinancing(projectSupport.getGetFinancing() + price);
            projectSupport.getSupportUserList().add(supportUser);
            projectSupport.setPeopleNum(projectSupport.getPeopleNum() + 1);
            order.setStatus(OrderStatus.ORDER_PAID);
            orderDao.update(order, token);
            projectSupportStore.save(projectSupport);

            UserSupportProject userSupportProject =userSupportProjectStore.searchSupportedProject(token.getOperatorUserId());
            if (userSupportProject == null) {
                userSupportProject = new UserSupportProject();
                userSupportProject.setUserId(user.getUserId());
            }
            List<Long> supportedProjectIdList = userSupportProject.getSupportedProjectIdList();
            boolean supported = false;
            for (Long id : supportedProjectIdList) {
                if (id == projectId) {
                    supported = true;
                    break;
                }
            }
            if (!supported) {
                supportedProjectIdList.add(projectId);
                userSupportProjectStore.save(userSupportProject);
            }



            for (OrderItem oi : order.getOrderItemSet()){
                SkuSupport skuSupport = skuSupoortStore.searchSkuSupportBySkuId(oi.getSkuId());
                if (skuSupport == null) {
                    skuSupport = new SkuSupport();
                    skuSupport.setProjectId(projectId);
                    skuSupport.setSkuId(oi.getSkuId());
                    skuSupport.setPeopleNum(skuSupport.getPeopleNum()+1);
                    skuSupoortStore.save(skuSupport);
                } else {
                    skuSupoortStore.updateSkuSupport(skuSupport.getSkuId());
                }
            }

            return true;
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public String refundByProject(SecurityToken token, RefundData refundData, JsonResponse obj) {
        Map<String, String> sParaTemp=new HashMap<String, String>();
        sParaTemp.put("service", "refund_fastpay_by_platform_pwd");
        sParaTemp.put("partner", AlipayConfig.partner);
        sParaTemp.put("_input_charset", AlipayConfig.input_charset);
        sParaTemp.put("seller_email", refundData.getPayUserName());
        sParaTemp.put("refund_date", ToolsImpl.serializeDateMMSS(new Date()));
        sParaTemp.put("notify_url",homeUrl+"/single/project/refund/notify");
        ProjectSupport projects = projectSupportStore.searchProjectSupport(refundData.getProjectId());
        UUID uuid =UUID.randomUUID();
        String batchNo = ToolsImpl.serializeDate(new Date()).replace("-","")+refundData.getProjectId();
        projects.setBatchNo(batchNo);
        projectSupportStore.save(projects);
        sParaTemp.put("batch_no",batchNo); //pi ci hao
        StringBuffer buffer = new StringBuffer();
        String resHtml="";
        if(projects ==null || projects.getSupportUserList().size() ==0) {
            JsonResponseHelper.addError(obj,CoreConstants.PROJECT_REFUND_NOTENOUGH);
        } else {
            for(SupportUser user:projects.getSupportUserList()) {
                if(user.getTradeNumber() == null){
                    JsonResponseHelper.addError(obj,CoreConstants.TRADE_NUMBER_EXIT);
                    return resHtml;
                }
                buffer.append(user.getTradeNumber()).append("^").append(String.valueOf(user.getPrice())).append("^").append("团购人数不足退款").append("#");
            }
            buffer.replace(buffer.length()-1,buffer.length(),"");

            sParaTemp.put("batch_num", String.valueOf(projects.getSupportUserList().size()));
            sParaTemp.put("detail_data",buffer.toString()); //detail data
            String strMethod="get";
            String strButtonName = "确认";
            resHtml = AlipaySubmit.buildRequest(sParaTemp,strMethod,strButtonName);
        }
        return resHtml;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public Map<String,String> signParam(JsonResponse obj, SecurityToken token, Long orderId) {
        Orders order = orderDao.getByOrderId(orderId);
        Map<String,String> sParaTemp = new ManagedMap<String, String>();
        Map<String, String> paramsMap = new ManagedMap<String, String>();
        if(order == null) {
            JsonResponseHelper.addError(obj, CoreConstants.ORDER_INVIAL);
        } else if (order.getStatus() == OrderStatus.ORDER_PAID) {
            JsonResponseHelper.addError(obj, CoreConstants.ORDER_PAID_ALREADY);
        } else {
            double price = 0L;
            String name = "";
            for (OrderItem orderItem : order.getOrderItemSet()) {
                price += orderItem.getSkus().getUnitprice() * orderItem.getUnits();
                name = orderItem.getSkus().getName();
            }
            DecimalFormat df = new DecimalFormat("######0.00");
            sParaTemp.put("partner", AlipayConfig.partner);
            sParaTemp.put("seller_id", AlipayConfig.seller_id);
            sParaTemp.put("out_trade_no", orderId.toString());
            sParaTemp.put("subject", name);
            sParaTemp.put("body", name);
            sParaTemp.put("total_fee", String.valueOf(df.format(price)));
            sParaTemp.put("notify_url", notifyUrl);
            sParaTemp.put("service", "mobile.securitypay.pay");
            sParaTemp.put("payment_type", "1");
            sParaTemp.put("_input_charset", AlipayConfig.input_charset);
            sParaTemp.put("it_b_pay", "3m");
            String preStr = AlipayCore.createLinkString(sParaTemp);
            String mySign = RSA.sign(preStr,AlipayConfig.private_key, AlipayConfig.input_charset);
            try {
                mySign = URLEncoder.encode(mySign, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            String params = new StringBuffer(preStr).
                    append("&").
                    append("sign=").
                    append(mySign).
                    append("&sign_type=").
                    append(AlipayConfig.sign_type).toString();
            // sParaTemp.put("return_url", returnUrl);
            //sParaTemp.put("show_url", homeUrl);
            //sParaTemp.put("extern_token", "");
            //sParaTemp = AlipaySubmit.buildRequestPara(sParaTemp);
            paramsMap.put("params",params);
        }
        return paramsMap;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void returnRefund( SecurityToken token,JsonResponse obj, String batchNo) {
        ProjectSupport support = projectSupportStore.getByBatchNo(batchNo);
        if(support != null){
            projectSupportStore.removeByBatchNo(batchNo);
        }else{
            JsonResponseHelper.addError(obj, CoreConstants.PROJECT_REFUND_FAIL);
        }
    }
}
